package cn.ai.shoes.core.controller;

import cn.ai.shoes.common.core.mybatis.LambdaQueryWrapperX;
import cn.ai.shoes.common.exception.ServiceException;
import cn.ai.shoes.common.exception.constant.GlobalErrorCodeConstants;
import cn.ai.shoes.common.pojo.entity.CommonResult;
import cn.ai.shoes.common.utils.RedisUtils;
import cn.ai.shoes.core.pojo.entity.MyUser;
import cn.ai.shoes.core.pojo.entity.SmsLoginForm;
import cn.ai.shoes.core.service.UserService;
import cn.ai.shoes.core.utils.*;
import cn.hutool.core.util.RandomUtil;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.aliyun.dysmsapi20170525.models.SendSmsResponseBody;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jodd.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Controller for "/".
 *
 * @author Joe Grandja
 */
@RestController
@Tag(name = "登录管理", description = "登录管理")
public class LoginController {
    @Resource
    private RedisUtils<String,String> strRedisUtils;
    @Resource
    private UserService userService;
    @Resource
    private JwtUtils jwtUtils;
    public static final String SMS_CODE_KEY = "sms:";
    /**
     * 短信登录
     * @return
     */
    @GetMapping("/sendSms")
    @Operation(summary = "发送短信", description = "发送短信")
    public CommonResult<?> smsLogin(@Schema(name = "phone",description = "手机号", required = true) String phone) throws Exception {
        //校验手机号
        if (!ValidationUtils.isPhone(phone)){
            throw new ServiceException(GlobalErrorCodeConstants.PHONE_FROM_ERROR);
        }
        SendSmsResponseBody sendSmsResponseBody = sendMsg(phone);
        //判断发送短信是否成功
        if (!sendSmsResponseBody.getCode().equals("OK")) {
            System.out.println("error:"+sendSmsResponseBody.getMessage());
            if (sendSmsResponseBody.getCode().equals("isv.BUSINESS_LIMIT_CONTROL")){
                throw new ServiceException(GlobalErrorCodeConstants.SMS_SEND_FREQUENTLY);
            }
            if (sendSmsResponseBody.getCode().equals("isv.MOBILE_NUMBER_ILLEGAL")){
                throw new ServiceException(GlobalErrorCodeConstants.PHONE_FROM_ERROR);
            }
            //今日发送短信次数已达上限
            if (sendSmsResponseBody.getCode().equals("isv.AMOUNT_LIMIT_CONTROL")){
                throw new ServiceException(GlobalErrorCodeConstants.SMS_SEND_LIMIT);
            }
            throw new ServiceException(GlobalErrorCodeConstants.SMS_SEND_ERROR);
        }

        return CommonResult.success(sendSmsResponseBody.getMessage());
    }

    @PostMapping("/smsLogin")
    @Operation(summary = "验证码登录", description = "验证码登录")
    public CommonResult<?> smslogin(@RequestBody @Validated SmsLoginForm form) throws IOException {
        //查询用户是否存在
        if (!userService.exists(new LambdaQueryWrapperX<MyUser>().eq(MyUser::getPhone, form.getPhone()))){
            throw new ServiceException(GlobalErrorCodeConstants.USER_NOT_EXIST);
        }
        //校验验证码
        if (!ValidationUtils.isPhone(form.getPhone())){
            throw new ServiceException(GlobalErrorCodeConstants.PHONE_FROM_ERROR);
        }
        //获取验证码
        String redisPhone = strRedisUtils.get(SMS_CODE_KEY + form.getCode());
        if(StringUtil.isEmpty(redisPhone)){
            throw new ServiceException(GlobalErrorCodeConstants.SMS_CODE_ERROR);
        }
        if (!redisPhone.equals(form.getPhone())){
            throw new ServiceException(GlobalErrorCodeConstants.SMS_CODE_ERROR);
        }
        //删除验证码
        strRedisUtils.del(SMS_CODE_KEY + form.getCode());
        UserDetails userDetails = AuthenticationUtils.createUserDetails(null, redisPhone, userService);

        //生成token
        String token = JwtUtils.generateJwt(userDetails);
        String authorization= getAuthorization(token);
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken
                (userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        String json = AuthenticationUtils.response(userDetails, userService, AuthenticationUtils.SMS_LOGIN_PROCESSOR);
        JSONObject result = JSON.parseObject(json);
        return CommonResult.success(result);
    }

    @NotNull
    private static String getAuthorization(String token) {
        return JwtUtils.getTokenPrefix() + " " + token;
    }

    @Nullable
    private SendSmsResponseBody sendMsg(String phone) throws Exception {
        Map<String, String> map = new HashMap<>();
        map.put("phoneNumber", phone);
        String code = RandomUtil.randomNumbers(4);
        strRedisUtils.save(SMS_CODE_KEY+code, phone);
        map.put("templateParam", JSON.toJSONString(Map.of("code",code)));
        return AliyunSmsUtils.sendSms(map);
    }
}
